﻿using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

// TODO: Upcount the version
[assembly: AssemblyVersion("0.3.5.*")]

namespace TileMaker
{
    public partial class MainWindow : Form
    {
        int OptimalWidth;
        int OptimalHeight;

        double VerticalDegPerPx;
        double HorizontalDegPerPx;

        TileCoordinates FirstTile;
        Rectangle SnappedTile;
        
        public static string GetVersion(bool complete)
        {
            Version ver = Assembly.GetExecutingAssembly().GetName().Version;

            if (complete) return String.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision);
            return String.Format("{0}.{1}", ver.Major, ver.Minor);
        }

        private string fName;
        public string FileName
        {
            get { return Path.GetFullPath(fName); }
            set
            {
                if (File.Exists(value))
                {
                    fName = value;
                    string Shown = Path.GetFullPath(value);
                    if (Shown.Length > 128) Shown = Path.GetFileName(value);

                    this.Text = "TileMaker v" + GetVersion(false) + " - " + Shown;
                }
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            InitPicBox();

            fName = String.Empty;
        }

        private void MainWindow_Load(object sender, EventArgs e)
        {
            if (Environment.GetCommandLineArgs().Count() > 1)
                if (!String.IsNullOrWhiteSpace(Environment.GetCommandLineArgs()[1]))
                    fName = Environment.GetCommandLineArgs()[1];
            
            if (String.IsNullOrWhiteSpace(fName))
                this.Text = "TileMaker v" + GetVersion(false) + " - New";
            else
                this.Text = "TileMaker v" + GetVersion(false) + " - " + FileName;

            PlanetList.SelectedIndex = 0;

            if (Environment.GetCommandLineArgs().Length > 0)
                PicLoad(Environment.GetCommandLineArgs()[1]);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (ImgOFD.ShowDialog() != DialogResult.OK) return;

            PicLoad(ImgOFD.FileName);
        }

        private void CalcTiles_Click(object sender, EventArgs e)
        {
            double Radius = 6371010; // To be changed by a dynamic database reader
            
            double PicWidth = PicBox.Image.Width;
            double PicHeight = PicBox.Image.Height;

            double TLlongitude = double.Parse(TLlong.Text);
            double TLlatitude = double.Parse(TLlat.Text);
            double BRlongitude = double.Parse(BRlong.Text);
            double BRlatitude = double.Parse(BRlat.Text);

            double TopLen = DistanceLon(TLlongitude, BRlongitude, TLlatitude, Radius);
            double BotLen = DistanceLon(TLlongitude, BRlongitude, BRlatitude, Radius);

            double LatLen = DistanceLat(TLlatitude, BRlatitude, Radius);

            double TopRes = TopLen / PicWidth;
            double BotRes = BotLen / PicWidth;

            VerticalDegPerPx = (BRlatitude - TLlatitude) / (double)PicHeight;
            HorizontalDegPerPx = (BRlongitude - TLlongitude) / (double)PicWidth;

            double LatRes = LatLen / PicHeight;

            int MaxLevel = 0;
            for (int i = 0; i < 11; i++)
            {
                double value = 360.0f / Math.Pow(2, 8 + i);
                MaxLevel = i;
                if (value - (512*VerticalDegPerPx) < 0) break;
                if (i == 10)
                {
                    MessageBox.Show("Wow           such details          wow\n      too many pixels             so much for Orbiter\n            wow\n\n" +
                                              "Seriously, your image is way too much detailed to work within Orbiter. Scale it down or select a larger area for the same dimensions.",
                                              "Much Details, Such pixels, Wow", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                }
            }

            int HorizontalTiles = (int)Math.Pow(2, 8 + MaxLevel);
            int VerticalTiles = HorizontalTiles / 2;

            FirstTile = new TileCoordinates((byte)MaxLevel, TLlatitude, TLlongitude);

            InfoTiles.Text = String.Format("Top Resolution: {0}/px - Bottom Resolution: {1}/px | Lateral Resolution: {2}/px",
                                            WithCorrectUnit(TopRes * 1000, "0.000"), WithCorrectUnit(BotRes * 1000, "0.000"), WithCorrectUnit(LatRes * 1000, "0.000")) + "\n" +
                                            String.Format("Tile Level: {0} | Tile Vertical Span: {1} | First Tile: {2}{3:0000} {4}{5:0000}", MaxLevel, WithCorrectUnit(DistanceLat(360.0f / Math.Pow(2, 8 + MaxLevel), 0, Radius), "0.00000"), FirstTile.Latitude>0?"N":"S", Math.Abs(FirstTile.Latitude), FirstTile.Longitude>0?"E":"W", Math.Abs(FirstTile.Longitude));

            TopSpan.Text = "Top Horizontal Span: " + WithCorrectUnit(TopLen*1000, "0.00000");
            BotSpan.Text = "Bottom Horizontal Span: " + WithCorrectUnit(BotLen*1000, "0.00000");
            LatSpan.NewText = "Vertical Span: " + WithCorrectUnit(BotLen*1000, "0.00000");
            

            //Top Left snap
            TileCoordinates TopLeft = new TileCoordinates(FirstTile.Level, FirstTile.Latitude + 1, FirstTile.Longitude);
            double TLatDiff = TLlatitude - TopLeft.LatitudeCoords;
            double TLonDiff = TLlongitude - TopLeft.LongitudeCoords;

            double TLatPxDiff = TLatDiff / VerticalDegPerPx;
            double TLonPxDiff = TLonDiff / HorizontalDegPerPx;

            // Bottom Right snap
            //TileCoordinates BottomRight = new TileCoordinates((byte)MaxLevel, FirstTile.Latitude+(int)(PicHeight/512), FirstTile.Longitude+(int)(PicWidth/512));
            //double BLatDiff = TLlatitude - BottomRight.LatitudeCoords;
            //double BLonDiff = TLlongitude - BottomRight.LongitudeCoords;

            //double BLatPxDiff = BLatDiff / VerticalDegPerPx;
            //double BLonPxDiff = BLonDiff / HorizontalDegPerPx;


            //SnappedTile = new Rectangle(new Point((int)Math.Round(TLonPxDiff), (int)Math.Round(TLatPxDiff)),
            //                            new Size((int)Math.Abs(BLonPxDiff), (int)Math.Abs(BLatPxDiff)));

            SnappedTile = new Rectangle(new Point((int)Math.Round(TLonPxDiff), (int)Math.Round(TLatPxDiff)),
                                        new Size((int)Math.Abs(OptimalWidth), (int)Math.Abs(OptimalHeight)));


            TopSpan.Visible = true;
            BotSpan.Visible = true;
            LatSpan.Visible = true;

            btnSplit.Enabled = true;
        }

        private void MainWindow_Resize(object sender, EventArgs e)
        {
            Rectangle parentRect = this.ClientRectangle;
            TopSpan.Left = (parentRect.Width - TopSpan.Width) / 2;
            BotSpan.Left = (parentRect.Width - BotSpan.Width) / 2;

            LatSpan.Top = (parentRect.Height - LatSpan.Height) / 2;
        }

        private void btnSplit_Click(object sender, EventArgs e)
        {            
            string Body = "Earth"; // To be changed by planet selector
            Split(PicBox.Image as Bitmap, 512, SnappedTile, Body, FirstTile);
        }

        private void SaveCoords_Click(object sender, EventArgs e)
        {
            string FileName = Path.ChangeExtension(PicBox.ImageLocation, "gps");
            File.WriteAllText(FileName, String.Format("TLlat={0}\nTLlong={1}\nBRlat={2}\nBRlong={3}", TLlat.Text, TLlong.Text, BRlat.Text, BRlong.Text));

            MessageBox.Show("Coordinates saved. Be sure to move \"" + Path.GetFileName(FileName) + "\" with the image if you have to.", "Save complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}
